From: Ian.Campbell@xensource.com Date: Fri, 21 Apr 2006 16:19:22 +0000 (+0100) Subject: Merge nmi_op functionality with the callback_op hypercall. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~16117^2~36 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=8c18405bb315412b8af78b8d90819430a5555f61;p=xen.git Merge nmi_op functionality with the callback_op hypercall. Signed-off-by: Ian Campbell --- diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h index 5107aacd4d..a349bb18a0 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h @@ -34,7 +34,10 @@ static void __init machine_specific_arch_setup(void) .type = CALLBACKTYPE_failsafe, .address = { __KERNEL_CS, (unsigned long)failsafe_callback }, }; - struct xennmi_callback cb; + struct callback_register nmi_cb = { + .type = CALLBACKTYPE_nmi, + .address = { __KERNEL_CS, (unsigned long)nmi }, + }; if (xen_feature(XENFEAT_auto_translated_physmap) && xen_start_info->shared_info < xen_start_info->nr_pages) { @@ -52,8 +55,14 @@ static void __init machine_specific_arch_setup(void) failsafe.address.cs, failsafe.address.eip); BUG_ON(ret); - cb.handler_address = (unsigned long)&nmi; - HYPERVISOR_nmi_op(XENNMI_register_callback, &cb); + ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb); + if (ret == -ENOSYS) { + struct xennmi_callback cb; + + cb.handler_address = nmi_cb.address.eip; + ret = HYPERVISOR_nmi_op(XENNMI_register_callback, &cb); + } + BUG_ON(ret); if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h index 725ea90c03..aca5ba7e65 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h @@ -28,7 +28,10 @@ static void __init machine_specific_arch_setup(void) .address = (unsigned long)system_call, }; #ifdef CONFIG_X86_LOCAL_APIC - struct xennmi_callback cb; + struct callback_register nmi_cb = { + .type = CALLBACKTYPE_nmi, + .address = (unsigned long)nmi, + }; #endif ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event); @@ -44,7 +47,13 @@ static void __init machine_specific_arch_setup(void) BUG_ON(ret); #ifdef CONFIG_X86_LOCAL_APIC - cb.handler_address = (unsigned long)&nmi; - HYPERVISOR_nmi_op(XENNMI_register_callback, &cb); + ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb); + if (ret == -ENOSYS) { + struct xennmi_callback cb; + + cb.handler_address = nmi_cb.address; + ret = HYPERVISOR_nmi_op(XENNMI_register_callback, &cb); + } + BUG_ON(ret); #endif } diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 085c126153..dfba38c566 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -336,6 +337,10 @@ static long register_guest_callback(struct callback_register *reg) v->arch.guest_context.failsafe_callback_eip = reg->address.eip; break; + case CALLBACKTYPE_nmi: + ret = register_guest_nmi_callback(reg->address.eip); + break; + default: ret = -EINVAL; break; @@ -350,6 +355,10 @@ static long unregister_guest_callback(struct callback_unregister *unreg) switch ( unreg->type ) { + case CALLBACKTYPE_nmi: + ret = unregister_guest_nmi_callback(); + break; + default: ret = -EINVAL; break; diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 4f5ff5ba11..62ac6fa1b5 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -339,6 +340,10 @@ static long register_guest_callback(struct callback_register *reg) v->arch.guest_context.syscall_callback_eip = reg->address; break; + case CALLBACKTYPE_nmi: + ret = register_guest_nmi_callback(reg->address); + break; + default: ret = -EINVAL; break; @@ -353,6 +358,10 @@ static long unregister_guest_callback(struct callback_unregister *unreg) switch ( unreg->type ) { + case CALLBACKTYPE_nmi: + ret = unregister_guest_nmi_callback(); + break; + default: ret = -EINVAL; break; diff --git a/xen/common/kernel.c b/xen/common/kernel.c index a2a23fb70f..f7dffadd69 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -213,37 +213,51 @@ long do_xen_version(int cmd, GUEST_HANDLE(void) arg) return -ENOSYS; } -long do_nmi_op(unsigned int cmd, GUEST_HANDLE(void) arg) +long register_guest_nmi_callback(unsigned long address) { struct vcpu *v = current; struct domain *d = current->domain; + + if ( (d->domain_id != 0) || (v->vcpu_id != 0) ) + return -EINVAL; + + v->nmi_addr = address; +#ifdef CONFIG_X86 + /* + * If no handler was registered we can 'lose the NMI edge'. Re-assert it + * now. + */ + if ( d->shared_info->arch.nmi_reason != 0 ) + set_bit(_VCPUF_nmi_pending, &v->vcpu_flags); +#endif + + return 0; +} + +long unregister_guest_nmi_callback(void) +{ + struct vcpu *v = current; + + v->nmi_addr = 0; + + return 0; +} + +long do_nmi_op(unsigned int cmd, GUEST_HANDLE(void) arg) +{ struct xennmi_callback cb; long rc = 0; switch ( cmd ) { case XENNMI_register_callback: - rc = -EINVAL; - if ( (d->domain_id != 0) || (v->vcpu_id != 0) ) - break; - rc = -EFAULT; if ( copy_from_guest(&cb, arg, 1) ) break; - - v->nmi_addr = cb.handler_address; -#ifdef CONFIG_X86 - /* - * If no handler was registered we can 'lose the NMI edge'. Re-assert - * it now. - */ - if ( d->shared_info->arch.nmi_reason != 0 ) - set_bit(_VCPUF_nmi_pending, &v->vcpu_flags); -#endif - rc = 0; + rc = register_guest_nmi_callback(cb.handler_address); break; case XENNMI_unregister_callback: - v->nmi_addr = 0; + rc = unregister_guest_nmi_callback(); break; default: rc = -ENOSYS; diff --git a/xen/include/public/callback.h b/xen/include/public/callback.h index 479333ddb8..27877c72ad 100644 --- a/xen/include/public/callback.h +++ b/xen/include/public/callback.h @@ -21,6 +21,7 @@ #define CALLBACKTYPE_event 0 #define CALLBACKTYPE_failsafe 1 #define CALLBACKTYPE_syscall 2 /* x86_64 only */ +#define CALLBACKTYPE_nmi 4 /* * Register a callback. diff --git a/xen/include/xen/nmi.h b/xen/include/xen/nmi.h index e526b6ab6f..a13e797273 100644 --- a/xen/include/xen/nmi.h +++ b/xen/include/xen/nmi.h @@ -11,4 +11,19 @@ #include +/** + * register_guest_nmi_callback + * + * The default NMI handler passes the NMI to a guest callback. This + * function registers the address of that callback. + */ +extern long register_guest_nmi_callback(unsigned long address); + +/** + * unregister_guest_nmi_callback + * + * Unregister a guest NMI handler. + */ +extern long unregister_guest_nmi_callback(void); + #endif /* __XEN_NMI_H__ */